package com.gxs.ea.fileupload.beans.jsf.company;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;

import org.primefaces.component.column.Column;
import org.primefaces.component.orderlist.OrderList;
import org.primefaces.component.panelgrid.PanelGrid;
import org.primefaces.component.row.Row;
import org.primefaces.event.FlowEvent;
import org.primefaces.event.RowEditEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.gxs.ea.fileportal.domain.BaseCompany;
import com.gxs.ea.fileportal.domain.CompanyMetaConfig;
import com.gxs.ea.fileportal.domain.Field;
import com.gxs.ea.fileupload.beans.data.service.CompanyService;
import com.gxs.ea.fileupload.beans.utils.JSFUtils;

@Component
@Scope("session")
public class ViewCompanyBean  implements Serializable
{
	private BaseCompany selectedCompany;
	private String selectedCompanyCode;
	private boolean pendingChanges = false; 
	//private boolean showCloseDialog = false;
	private boolean hideDialog = false;
	private boolean hideHeadingDialog = false;
	
	private String selectedGroupingForInputForm;
	private String selectedGroupingForOutputForm;
	
	private String tempInputFieldGrouping;
	private Field tempField = new Field();
	
	private List tempListOrderOfFieldsInputForm;
	private List tempListOrderOfFieldsOutputForm;
	
	private boolean dynamicViewsHaveBeenInitialized = false;
	
	private int activeTabIndex = 0;
	
	private String activeWizardTab ="basicInfo";
	
	private boolean existingFieldBeingEdited = false;
	
	private boolean skip;
	@Autowired
	private CompanyService companyService;
	
	@Autowired
	private JSFUtils jsfUtils;
	
	public String onFlowProcess(FlowEvent event) 
	{  
          
        if(skip) // we have not implemented skip - so this will never be true 
        {  
            skip = false;   //reset in case user goes back  
            return "confirm";  
        } 
        else if(event.getOldStep().equals("basicInfo"))
        {
        	return processNextFromBasicInfo(event);
        }
        else if(event.getOldStep().equals("sourceInfo") && event.getNewStep().equals("displayInfo"))
        {
        	return processNextFromSourceInfo(event);
        }
        else if(event.getOldStep().equals("displayInfo") && event.getNewStep().equals("confirmation"))
        {
        	return processNextFromDisplayInfo(event);
        }
        else 
        {
            return event.getNewStep();  
        }  
    }  
	
	private String processNextFromDisplayInfo(FlowEvent event) 
	{
		boolean hasErrors = false;
		
		if(tempField.isFilterable())
		{
			String fieldType = tempField.getFieldType();
			
			if(fieldType.equals(Field.FIELD_TYPE_STRING) || fieldType.equals(Field.FIELD_TYPE_INTEGER))
			{
				// okay
			}
			else
			{
				jsfUtils.printError("Error:", "(Currently) Filtering is only available on STRING and INTEGER types, and your field type is: " + fieldType);
				hasErrors = true;
			}
		}

		if(tempField.isSearchable())
		{
			String fieldType = tempField.getFieldType();
			
			if(fieldType.equals(Field.FIELD_TYPE_STRING) || fieldType.equals(Field.FIELD_TYPE_INTEGER))
			{
				// okay
			}
			else
			{
				jsfUtils.printError("Error:", "(Currently) Searching is only available on STRING and INTEGER types, and your field type is: " + fieldType);
				hasErrors = true;
			}
		}

		
		
		if(hasErrors)
			return event.getOldStep();
		else
			return event.getNewStep();
	}

	private String processNextFromSourceInfo(FlowEvent event) 
	{
    	String selection = this.tempField.getFieldSource();
    	boolean hasErrors = false;
    	
    	if(StringUtils.isEmpty(selection))
    	{
    		jsfUtils.printError("Error:", "Your must select the source type of data for this field");
    		hasErrors = true;
    	}
    	
    	if(selection.equals(Field.FIELD_SOURCE_USER_ENTERED))
    	{
    		// dont' set any errors
    	}
    	else if(selection.equals(Field.FIELD_SOURCE_USER_ENTERED_LOV))
    	{
    		if(validateLovSelectionOnlyForString())
    		{
    			if(StringUtils.isEmpty(tempField.getTempListOfValuesDelimited()))
    			{
    				jsfUtils.printError("Error:", "You must provide list of value options when the source type if list of values");
    				hasErrors = true;
    			}

    		}
    		else
    		{
    			hasErrors = true;
    		}
    	}
    	else if(selection.equals(Field.FIELD_SOURCE_AUTO))
    	{
    		String autoSelection = this.tempField.getFieldAutoOptionSelected();
    		
    		if(StringUtils.isEmpty(autoSelection))
    		{
    			jsfUtils.printError("Error:", "You must select an option for auto-population of this field");
    			hasErrors = true;
    		}
    		
    		if(validateAutoOptionSelectionWithFieldType())
    		{
    			// good
    		}
    		else
    		{
    			hasErrors = true;
    		}
    	}
    	else if(selection.equals(Field.FIELD_SOURCE_EXTRACTED))
    	{
    		
    		if(StringUtils.isEmpty(tempField.getFieldExtractedDataPath()))
    		{
    			jsfUtils.printError("Error:", "You must provide path into data file segment where this value can be extracted from");
    			hasErrors = true;
    		}
    		else
    		{
    			// good
    		}
    	}
    	else
    	{
    		// good
    	}
    	
    	if(hasErrors)
    	{
    		return event.getOldStep();
    	}
    	else
    	{
    		clearUnusedFieldsInSourceSelectionScreen();
    		return event.getNewStep();
    	}
    	
	}

	private void clearUnusedFieldsInSourceSelectionScreen() 
	{
		String selection = tempField.getFieldSource();
		
		if(selection.equals(Field.FIELD_SOURCE_USER_ENTERED))
		{
			tempField.setFieldAutoOptionSelected(null);
			tempField.setFieldExtractedDataPath(null);
			tempField.setTempListOfValuesDelimited(null);
		}
		else if(selection.equals(Field.FIELD_SOURCE_USER_ENTERED_LOV))
		{
			tempField.setFieldAutoOptionSelected(null);
			tempField.setFieldExtractedDataPath(null);
			//tempField.setTempListOfValuesDelimited(null);
		}
		else if(selection.equals(Field.FIELD_SOURCE_AUTO))
		{
			//tempField.setFieldAutoOptionSelected(null);
			tempField.setFieldExtractedDataPath(null);
			tempField.setTempListOfValuesDelimited(null);
		}
		else if(selection.equals(Field.FIELD_SOURCE_EXTRACTED))
		{
			tempField.setFieldAutoOptionSelected(null);
			//tempField.setFieldExtractedDataPath(null);
			tempField.setTempListOfValuesDelimited(null);
		}
		else
		{
			// dont clear anything
		}
		
	}

	private String processNextFromBasicInfo(FlowEvent event) 
	{
    	if(event.getNewStep().equals("basicInfo"))
    	{
    		// this is initial invocation. dont' validate
    		return event.getNewStep();
    	}
    	
    	boolean hasErrors = false;
    	
    	if(StringUtils.isEmpty(tempField.getFieldName() ) )
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "Field Name is required");
    		hasErrors = true;
    	}
    	
    	
    	if(StringUtils.containsWhitespace(tempField.getFieldName()))
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "Field Name cannot contain space(s).");
    		hasErrors = true;
    	}
    	
    	if(doesFieldExistAlready(tempField.getFieldName()) && !existingFieldBeingEdited )
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "A field with this name has already been created");
    		hasErrors = true;
    	}

    	if(StringUtils.isEmpty(tempField.getFieldDisplayName() ) )
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "Field Display Name is required");
    		hasErrors = true;
    	}

    	if(StringUtils.isEmpty(tempField.getFieldGrouping() ) )
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "Field Grouping is required");
    		hasErrors = true;
    	}
    	
    	if(StringUtils.isEmpty(tempField.getFieldType()) )
    	{
    		jsfUtils.printError("createFieldMessages", "Error:", "Field Type is required");
    		hasErrors = true;
    	}
    	
    	if(hasErrors)
    		return event.getOldStep();
    	else
    		return event.getNewStep();  

	}

	private void clearFields()
	{
		this.selectedCompany = null;
	}
	
	public JSFUtils getJsfUtils() {
		return jsfUtils;
	}

	public void setJsfUtils(JSFUtils jsfUtils) {
		this.jsfUtils = jsfUtils;
	}

	private void clearTempFields()
	{
		tempInputFieldGrouping = null;
		tempField = new Field();
	}
	
	
	public Field getTempField() {
		return tempField;
	}

	public void setTempField(Field tempField) {
		this.tempField = tempField;
	}

	public BaseCompany getSelectedCompany() {
		return selectedCompany;
	}

	public void setSelectedCompany(BaseCompany selectedCompany) {
		this.selectedCompany = selectedCompany;
	}

	public CompanyService getCompanyService() {
		return companyService;
	}

	public void setCompanyService(CompanyService companyService) {
		this.companyService = companyService;
	}

	public String getSelectedCompanyCode() {
		return selectedCompanyCode;
	}

	private void initialize()
	{
		pendingChanges = false;
		hideDialog = false;
		hideHeadingDialog = false;
		clearTempFields();
		//showCloseDialog = false;
		
		this.selectedCompany = this.companyService.findByCompanyCode(selectedCompanyCode);
		
		if(selectedCompany.getCompanyMetaConfig() != null)
		{
			this.selectedGroupingForInputForm = selectedCompany.getCompanyMetaConfig().getFieldGropuings().get(0);
			this.selectedGroupingForOutputForm = selectedCompany.getCompanyMetaConfig().getFieldGropuings().get(0);
		}
		
		this.renderDynamicFields();
	
	}
	
	public void prepareForNewFieldGrouping()
	{
		this.tempInputFieldGrouping = null;
	}
	
	public void setSelectedCompanyCode(String selectedCompanyCode) 
	{
		this.selectedCompanyCode = selectedCompanyCode;
		this.dynamicViewsHaveBeenInitialized = false;
		this.activeTabIndex=0;
		initialize();
	}

	public String getTempInputFieldGrouping() {
		return tempInputFieldGrouping;
	}

	public void setTempInputFieldGrouping(String tempInputFieldGrouping) {
		this.tempInputFieldGrouping = tempInputFieldGrouping;
	}
	
	public void createFieldGrouping()
	{
		String groupingText = tempInputFieldGrouping;
		
		if(StringUtils.isEmpty(groupingText))
		{
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Input", ": You must provide a non-empty grouping id" ));
			hideHeadingDialog = false;
			return;
		}
		
		if(this.selectedCompany.getCompanyMetaConfig() == null)
		{
			this.selectedCompany.setCompanyMetaConfig(new CompanyMetaConfig());
		}
		
		List<String> currentGroupings = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings();
		
		if(currentGroupings.contains(groupingText))
		{
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Input", ": The specified grouping id " + groupingText  + " already exists in this configuration" ));
			hideHeadingDialog = false;
			return;
		}
		
		currentGroupings.add(groupingText);
		
		this.selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().put(groupingText, new ArrayList<String>());
		this.selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().put(groupingText, new ArrayList<String>());
		this.selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputSummaryTable().put(groupingText, new ArrayList<String>());
		
		
		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Success", ": Field Grouping successfully added -- Remember to save pending changes" ));
		pendingChanges = true;
		
		hideHeadingDialog = true;
		tempInputFieldGrouping = null;
		
		renderDynamicFields(); // this will ensure that the new additions are also reflected on the dynamically generated pages. 
		
	}

	public void createField()
	{
		
		if(StringUtils.isEmpty(tempField.getFieldName()))
		{
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Input", ": Field name is required" ));
			return;
		}
		
		if(existingFieldBeingEdited)
		{
			BaseCompany savedCompany = this.companyService.findByCompanyCode(this.selectedCompany.getCompanyCode());
			Field previousField = null;
			for (Field oldField : savedCompany.getCompanyMetaConfig().getFields())
			{
				if(oldField.getFieldName().equals(tempField.getFieldName())   ) 
				{
					previousField = oldField;
					break;
				}
			}
			
			//
			// previous field can be null if the user tries to 'edit' the field
			// while it was still transient (only on the UI and changes not saved yet
			// in that case, skip the evaluation of whether grouping has changed
			
			if(previousField == null)
			{
				// do nothing
			}
			else if( ! previousField.getFieldGrouping().equals(tempField.getFieldGrouping() ) )
			{
				// heading has changed
				List<String> tempList = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().get(previousField.getFieldGrouping());
				tempList.remove(tempField.getFieldName());
				
				tempList = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().get(previousField.getFieldGrouping());
				tempList.remove(tempField.getFieldName());
				
				tempList = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputSummaryTable().get(previousField.getFieldGrouping());
				tempList.remove(tempField.getFieldName());
				
				//
				// REadd to mapped ordered lists
				List<String> orderedListForInputForm = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().get(tempField.getFieldGrouping());
				orderedListForInputForm.add(tempField.getFieldName());

			}
			
			putFieldInOutputDetailSection(tempField);
			putFieldInOutputSummarySection(tempField);
			renderDynamicFields();

		}
		else
		{
			selectedCompany.getCompanyMetaConfig().getFields().add(tempField);

			//
			// Add to map of fields for input form
			List<String> orderedListForInputForm = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().get(tempField.getFieldGrouping());
			if(orderedListForInputForm == null)
			{
				orderedListForInputForm = new ArrayList<String>();
				selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().put(tempField.getFieldGrouping(), orderedListForInputForm);
			}
			orderedListForInputForm.add(tempField.getFieldName());

			putFieldInOutputDetailSection(tempField);
			putFieldInOutputSummarySection(tempField);

		}

		if(existingFieldBeingEdited)
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Success", ": Field successfully updated -- Remember to save pending changes" ));
		else
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Success", ": Field successfully added -- Remember to save pending changes" ));
		pendingChanges = true;
		//showCloseDialog = true;
		clearTempFields();
		
		hideDialog = true;
		
	}

	private void putFieldInOutputSummarySection(Field givenField) 
	{
		//
		// Add to map of fields for output form
		List<String> orderedListForSummaryTable = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputSummaryTable().get(givenField.getFieldGrouping());
		if(orderedListForSummaryTable == null)
		{
			orderedListForSummaryTable = new ArrayList<String>();
			selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputSummaryTable().put(givenField.getFieldGrouping(), orderedListForSummaryTable);
		}
		
		if(givenField.isShowInSummaryTable())
		{
			if(! orderedListForSummaryTable.contains(givenField.getFieldName()) )
				orderedListForSummaryTable.add(givenField.getFieldName());
		}
		else
		{
			if( orderedListForSummaryTable.contains(givenField.getFieldName()) )
				orderedListForSummaryTable.remove(givenField.getFieldName());
		}
		
	}

	
	private void putFieldInOutputDetailSection(Field givenField) 
	{
		//
		// Add to map of fields for output form
		List<String> orderedListForOutputForm = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().get(givenField.getFieldGrouping());
		if(orderedListForOutputForm == null)
		{
			orderedListForOutputForm = new ArrayList<String>();
			selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().put(givenField.getFieldGrouping(), orderedListForOutputForm);
		}
		
		if(givenField.isShowInDetailsPane() )
		{
			if(! orderedListForOutputForm.contains(givenField.getFieldName()) )
				orderedListForOutputForm.add(givenField.getFieldName());
		}
		else
		{
			if( orderedListForOutputForm.contains(givenField.getFieldName()) )
				orderedListForOutputForm.remove(givenField.getFieldName());
		}
		
	}

	public boolean isPendingChanges() {
		return pendingChanges;
	}

	public void setPendingChanges(boolean pendingChanges) {
		this.pendingChanges = pendingChanges;
	}
	
	public void savePendingChanges()
	{
		try
		{
			this.companyService.updateCompany(selectedCompany);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Success", ": Pending changes saved successfully" ));
			initialize(); // this will reload the components of this page
		}
		catch(Exception e)
		{
			e.printStackTrace();
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Error in Saving", ": Failed to save pending changes with error: " + e.getMessage() ));
		}
	}

	public String getSelectedGroupingForInputForm() {
		return selectedGroupingForInputForm;
	}

	public void setSelectedGroupingForInputForm(String selectedGroupingForInputForm) {
		this.selectedGroupingForInputForm = selectedGroupingForInputForm;
	}

	public String getSelectedGroupingForOutputForm() {
		return selectedGroupingForOutputForm;
	}

	public List<String> getTempListOrderOfFieldsInputForm() 
	{
		List<String> list = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().get(selectedGroupingForInputForm);
		if(list == null)
		{
			list = new ArrayList<String>();
			selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().put(selectedGroupingForInputForm, list);
		}
		
		return list; 
	}
	
	public void sortPerformedOnInputList()
	{
		int i=0; 
		System.out.println("Sort perofrmed on input list");
	}

	public List<String> getTempListOrderOfFieldsOutputForm() 
	{
		List<String> list = selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().get(selectedGroupingForOutputForm);
		if(list == null)
		{
			list = new ArrayList<String>();
			 selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().put(selectedGroupingForOutputForm, list);

		}
		
		return list; 
	}

	public void setSelectedGroupingForOutputForm(String selectedGroupingForOutputForm) 
	{
		this.selectedGroupingForOutputForm = selectedGroupingForOutputForm;
	}

	public void setTempListOrderOfFieldsInputForm(List given) 
	{
		System.out.println("Saving list of given: " + given);
		selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().put(selectedGroupingForInputForm,given);
	}

	public void setTempListOrderOfFieldsOutputForm(List given) 
	{
		selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().put(selectedGroupingForOutputForm,given);
	}
	
	public void handleChange(ValueChangeEvent event)
	{
		System.out.println("one click, selected gropuing: " + this.selectedGroupingForInputForm);
		System.out.println(selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().get(selectedGroupingForInputForm) );

		System.out.println("Old value: " + event.getOldValue());
	    System.out.println("New value: " + event.getNewValue());
		//selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForInputForm().put(selectedGroupingForInputForm,tempListOrderOfFieldsInputForm);

	}

	public void onSelect()
	{
		System.out.println("on select");
	}
	public void onClick()
	{
	}
	public void saveCurrentOrderInOutputForm()
	{
		selectedCompany.getCompanyMetaConfig().getMapOfOrderedFieldsForOutputDetailsForm().put(selectedGroupingForOutputForm,tempListOrderOfFieldsOutputForm);
	}
	
	public void renderDynamicFields()
	{
		this.renderDynamicFieldsForInputForm();
		this.renderDynamicFieldsForOutputForm();
		this.renderDynamicFieldsForOutputTable();

	}

	public void renderDynamicFieldsForInputForm()
	{
		UIComponent container = jsfUtils.findComponent(":mainForm:tabs:outputPanel");

		if(container == null)
			return;
		
		dynamicViewsHaveBeenInitialized = true;
		container.getChildren().clear();

		PanelGrid panelGrid = new PanelGrid();
		panelGrid.setStyleClass("noBorderGrid");
		container.getChildren().add(panelGrid);

		int numberOFColsInARow = 3;
		int numberOfFieldGroupings = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().size();
		
		if(numberOfFieldGroupings < 1)
		{
			// don't add anything
			return;
		}
		
		
		// Now determine how many rows we need
//		int numberOfRows = (numberOfFieldGroupings / numberOFColsInARow ) + (numberOfFieldGroupings % numberOFColsInARow);
		int numberOfRows = (numberOfFieldGroupings / numberOFColsInARow );
		if(numberOfFieldGroupings % numberOFColsInARow != 0)
			numberOfRows++;

		int partialColumns = numberOfFieldGroupings % numberOFColsInARow;
		int currentRowNumber = 0;
		Iterator<String> headingIterator = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().iterator();
		String heading = null;
		for (int i=0; i<numberOfRows; i++) 
		{
			currentRowNumber++;
			Row row = new Row();
			panelGrid.getChildren().add(row);
			boolean isLastRow = currentRowNumber == numberOfRows;
			int currentColumnNumber = 0;
			for (int j=0; j<numberOFColsInARow; j++)	
			{
				currentColumnNumber++;
				//
				// Identify if there is data to display for the current column
				// in this row
				
				Column col = new Column();
				row.getChildren().add(col);
				
				//
				// Idnetify if this is a filler column
				if(isLastRow && currentColumnNumber > partialColumns && partialColumns != 0)
				{
					// put nothing in this column
				}
				else
				{
						heading = headingIterator.next();
					
						OrderList list = new OrderList();
						col.getChildren().add(list);

						String expressionString = "#{viewCompanyBean.selectedCompany.companyMetaConfig.mapOfOrderedFieldsForInputForm['HEADING']}";
						expressionString = expressionString.replace("HEADING", heading);
						ValueExpression expression = jsfUtils
								.createValueExpression(expressionString);
						list.setValueExpression("value", expression);
						list.setVar("row");
						list.setValueExpression("itemLabel",
								jsfUtils.createValueExpression("#{row}"));
						list.setValueExpression("itemValue",
								jsfUtils.createValueExpression("#{row}"));
						list.setStyleClass("noBorderGrid");

						list.setControlsLocation("none");
						list.setStyle("margin-left:0px;margin-top:5px;");

						UIOutput facetsCaption = (UIOutput) FacesContext
								.getCurrentInstance().getApplication()
								.createComponent(UIOutput.COMPONENT_TYPE);
						facetsCaption.setValue("Fields for: " + heading);
						list.getFacets().put("caption", facetsCaption);
				}

			}
		}
		
	}

	public void renderDynamicFieldsForOutputForm()
	{
		UIComponent container = jsfUtils.findComponent(":mainForm:tabs:outputPanelForOutput");

		if(container == null)
			return;
		
		dynamicViewsHaveBeenInitialized = true;
		container.getChildren().clear();

		PanelGrid panelGrid = new PanelGrid();
		panelGrid.setStyleClass("noBorderGrid");
		container.getChildren().add(panelGrid);

		int numberOFColsInARow = 3;
		int numberOfFieldGroupings = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().size();
		
		if(numberOfFieldGroupings < 1)
		{
			// don't add anything
			return;
		}
		
		
		// Now determine how many rows we need
		int numberOfRows = (numberOfFieldGroupings / numberOFColsInARow );
		if(numberOfFieldGroupings % numberOFColsInARow != 0)
			numberOfRows++;

		int partialColumns = numberOfFieldGroupings % numberOFColsInARow;
		int currentRowNumber = 0;
		Iterator<String> headingIterator = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().iterator();
		String heading = null;
		for (int i=0; i<numberOfRows; i++) 
		{
			currentRowNumber++;
			Row row = new Row();
			panelGrid.getChildren().add(row);
			boolean isLastRow = currentRowNumber == numberOfRows;
			int currentColumnNumber = 0;
			for (int j=0; j<numberOFColsInARow; j++)	
			{
				currentColumnNumber++;
				//
				// Identify if there is data to display for the current column
				// in this row
				
				Column col = new Column();
				row.getChildren().add(col);
				
				//
				// Idnetify if this is a filler column
				if(isLastRow && currentColumnNumber > partialColumns && partialColumns != 0)
				{
					// put nothing in this column
				}
				else
				{
						heading = headingIterator.next();
					
						OrderList list = new OrderList();
						col.getChildren().add(list);

						String expressionString = "#{viewCompanyBean.selectedCompany.companyMetaConfig.mapOfOrderedFieldsForOutputDetailsForm['HEADING']}";
						expressionString = expressionString.replace("HEADING", heading);
						ValueExpression expression = jsfUtils
								.createValueExpression(expressionString);
						list.setValueExpression("value", expression);
						list.setVar("row");
						list.setValueExpression("itemLabel",
								jsfUtils.createValueExpression("#{row}"));
						list.setValueExpression("itemValue",
								jsfUtils.createValueExpression("#{row}"));
						list.setStyleClass("noBorderGrid");

						list.setControlsLocation("none");
						list.setStyle("margin-left:0px;margin-top:5px;");

						UIOutput facetsCaption = (UIOutput) FacesContext
								.getCurrentInstance().getApplication()
								.createComponent(UIOutput.COMPONENT_TYPE);
						facetsCaption.setValue("Fields for: " + heading);
						list.getFacets().put("caption", facetsCaption);
				}

			}
		}
		
	}

	public void renderDynamicFieldsForOutputTable()
	{
		UIComponent container = jsfUtils.findComponent(":mainForm:tabs:outputPanelForOutputTable");

		if(container == null)
			return;
		
		dynamicViewsHaveBeenInitialized = true;
		container.getChildren().clear();

		PanelGrid panelGrid = new PanelGrid();
		panelGrid.setStyleClass("noBorderGrid");
		container.getChildren().add(panelGrid);

		int numberOFColsInARow = 3;
		int numberOfFieldGroupings = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().size();
		
		if(numberOfFieldGroupings < 1)
		{
			// don't add anything
			return;
		}
		
		
		// Now determine how many rows we need
		int numberOfRows = (numberOfFieldGroupings / numberOFColsInARow );
		if(numberOfFieldGroupings % numberOFColsInARow != 0)
			numberOfRows++;

		int partialColumns = numberOfFieldGroupings % numberOFColsInARow;
		int currentRowNumber = 0;
		Iterator<String> headingIterator = this.selectedCompany.getCompanyMetaConfig().getFieldGropuings().iterator();
		String heading = null;
		for (int i=0; i<numberOfRows; i++) 
		{
			currentRowNumber++;
			Row row = new Row();
			panelGrid.getChildren().add(row);
			boolean isLastRow = currentRowNumber == numberOfRows;
			int currentColumnNumber = 0;
			for (int j=0; j<numberOFColsInARow; j++)	
			{
				currentColumnNumber++;
				//
				// Identify if there is data to display for the current column
				// in this row
				
				Column col = new Column();
				row.getChildren().add(col);
				
				//
				// Idnetify if this is a filler column
				if(isLastRow && currentColumnNumber > partialColumns && partialColumns != 0)
				{
					// put nothing in this column
				}
				else
				{
						heading = headingIterator.next();
					
						OrderList list = new OrderList();
						col.getChildren().add(list);

						String expressionString = "#{viewCompanyBean.selectedCompany.companyMetaConfig.mapOfOrderedFieldsForOutputSummaryTable['HEADING']}";
						expressionString = expressionString.replace("HEADING", heading);
						ValueExpression expression = jsfUtils
								.createValueExpression(expressionString);
						list.setValueExpression("value", expression);
						list.setVar("row");
						list.setValueExpression("itemLabel",
								jsfUtils.createValueExpression("#{row}"));
						list.setValueExpression("itemValue",
								jsfUtils.createValueExpression("#{row}"));
						list.setStyleClass("noBorderGrid");

						list.setControlsLocation("none");
						list.setStyle("margin-left:0px;margin-top:5px;");

						UIOutput facetsCaption = (UIOutput) FacesContext
								.getCurrentInstance().getApplication()
								.createComponent(UIOutput.COMPONENT_TYPE);
						facetsCaption.setValue("Fields for: " + heading);
						list.getFacets().put("caption", facetsCaption);
				}

			}
		}
		
	}

	public void onEdit(RowEditEvent event) 
	{  
		Field f = (Field) event.getObject();
        this.putFieldInOutputDetailSection(f);
        this.putFieldInOutputSummarySection(f);
        renderDynamicFields();
    }  	
	
	public void onCancel()
	{
		System.out.println("On cancel called");
	}

	public int getActiveTabIndex() {
		return activeTabIndex;
	}

	public void setActiveTabIndex(int activeTabIndex) {
		this.activeTabIndex = activeTabIndex;
	}

	public boolean isHideDialog() {
		return hideDialog;
	}

	public void setHideDialog(boolean hideDialog) {
		this.hideDialog = hideDialog;
	}

	public boolean isHideHeadingDialog() {
		return hideHeadingDialog;
	}

	public void setHideHeadingDialog(boolean hideHeadingDialog) {
		this.hideHeadingDialog = hideHeadingDialog;
	}

	public boolean isSkip() {
		return skip;
	}

	public void setSkip(boolean skip) {
		this.skip = skip;
	}

	public String getActiveWizardTab() {
		return activeWizardTab;
	}

	public void setActiveWizardTab(String activeWizardTab) {
		this.activeWizardTab = activeWizardTab;
	}
	
	public void fieldDialogClosed()
	{
		//this.activeWizardTab = "basicInfo";
		this.tempField = new Field();
	}
	
	public void prepareForCreateNewField()
	{
		existingFieldBeingEdited = false;
		this.tempField = new Field();
	}
	public void prepareForEditField(Field field)
	{
		existingFieldBeingEdited = true;
		this.tempField = field;
	}
	
	public boolean doesFieldExistAlready(String fieldName)
	{
		for(Field f : this.selectedCompany.getCompanyMetaConfig().getFields())
		{
			if (f.getFieldName().equals(fieldName))
			{
				return true;
			}
		}
		
		return false;
	}
	
	
	public boolean validateAutoOptionSelectionWithFieldType()
	{
		String selection = this.tempField.getFieldAutoOptionSelected();
		String fieldType = tempField.getFieldType();
		if(Field.AUTO_OPTIONS_COMPANY_CODE.equals(selection))
		{
			if(fieldType.equals(Field.FIELD_TYPE_STRING))
			{
				return true;
			}
			else
			{
				jsfUtils.printError("Error:", "The type of this field is: "  + fieldType + ", but 'Company Code' is only available for String types");
				return false;
			}
		}
		else if(Field.AUTO_OPTIONS_CURRENT_USER.equals(selection))
		{
			if(fieldType.equals(Field.FIELD_TYPE_STRING))
			{
				return true;
			}
			else
			{
				jsfUtils.printError("Error:", "The type of this field is: "  + fieldType + ", but 'Current User' is only available for String types");
				return false;
			}
		}
		else if(Field.AUTO_OPTIONS_CURRENT_DATE.equals(selection))
		{
			if(fieldType.equals(Field.FIELD_TYPE_DATE))
			{
				return true;
			}
			else
			{
				jsfUtils.printError("Error:", "The type of this field is: "  + fieldType + ", but 'Current Date' is only available for Date types");
				return false;
			}
		}
		else if(Field.AUTO_OPTIONS_CURRENT_TIMESTAMP.equals(selection))
		{
			if(fieldType.equals(Field.FIELD_TYPE_TIMESTAMP))
			{
				return true;
			}
			else
			{
				jsfUtils.printError("Error:", "The type of this field is: "  + fieldType + ", but 'Current Timestamp' is only available for Timestamp types");
				return false;
			}
		}

		
		return true;
		
	}
	
	public boolean validateLovSelectionOnlyForString()
	{
		String selection = this.tempField.getFieldSource();
		
		if(Field.FIELD_SOURCE_USER_ENTERED_LOV.equals(selection) )
		{
			if(tempField.getFieldType().equals(Field.FIELD_TYPE_STRING)) 
			{
				// okay
			}
			else
			{
				jsfUtils.printError("Error:", "(Currently) List of Values are only available for fields of type String");
				return false;
			}
		}
		
		return true;
		
	}
	
	public boolean renderFieldRequiredOption()
	{
		if(this.tempField == null)
		{
			return false;
		}
		else if(this.tempField.getFieldSource().equals(Field.FIELD_SOURCE_AUTO))
		{
			return false;
		}
		else if(this.tempField.getFieldSource().equals(Field.FIELD_SOURCE_EXTRACTED))
		{
			return false;
		}
		else if(this.tempField.getFieldSource().equals(Field.FIELD_SOURCE_USER_ENTERED))
		{
			return true;
		}
		else if(this.tempField.getFieldSource().equals(Field.FIELD_SOURCE_USER_ENTERED_LOV))
		{
			return true;
		}
		else
		{
			return false;
		}

		
	}

	public boolean isExistingFieldBeingEdited() {
		return existingFieldBeingEdited;
	}

	public void setExistingFieldBeingEdited(boolean existingFieldBeingEdited) {
		this.existingFieldBeingEdited = existingFieldBeingEdited;
	}
	
	
}
